import { useState, useEffect } from 'react' import { Link, Navigate } from 'react-router-dom' import { ActionGroup, Transaction } from '@prisma/client' import { inferQueryOutput, trpc, useQueryClient } from '~/utils/trpc' import PageHeading from '~/components/PageHeading' import SectionHeading from '~/components/SectionHeading' import useDashboard, { useHasPermission } from '~/components/DashboardContext' import { dateTimeFormatter } from '~/utils/formatters' import IVUnstyledButtonOrLink, { IVUnstyledButtonOrLinkProps, } from '~/components/IVUnstyledButtonOrLink' import IVStatusPill from '~/components/IVStatusPill' import IconActions from '~/icons/compiled/Actions' import IconCancel from '~/icons/compiled/Cancel' import IconCircledPlay from '~/icons/compiled/CircledPlay' import EmptyState from '~/components/EmptyState' import QueuedActionsList from '~/components/QueuedActionsList' import Dialog, { useDialogState } from '~/components/IVDialog' import IVButton from '~/components/IVButton' import ActionsList from '~/components/ActionsList' import { getName } from '~/utils/actions' import { useOrgParams } from '~/utils/organization' import PageUI from '~/components/PageUI' import IVSpinner from '~/components/IVSpinner' interface TransactionAccessoryButtonProps extends IVUnstyledButtonOrLinkProps { icon: React.ComponentType> } export function TransactionAccessoryButton( props: TransactionAccessoryButtonProps ) { return ( {props.children} ) } function DashboardEmptyState() { const canAccessDev = useHasPermission('READ_DEV_ACTIONS') return (

Actions are the internal tools you build with Interval, created from within your project's codebase.

{canAccessDev && (

Visit the Development environment {' '} to install the SDK and develop your first actions. Then{' '} create a live key {' '} and{' '} deploy {' '} for them to appear here.

)} } actions={ canAccessDev ? [ { theme: 'secondary', href: `/dashboard/develop/actions`, label: Go to Development ›, }, ] : undefined } /> ) } function PageEmptyState() { return (

Add actions {' '} to this route or{' '} render a layout {' '} to populate this page.

} /> ) } function TransactionList({ organization, transactions, onCancel, }: { organization: { id: string; slug: string } transactions: inferQueryOutput<'dashboard.home.index'>['transactions'] onCancel: (transaction: Transaction) => void }) { const [cancelId, setCancelId] = useState(null) const cancelDialog = useDialogState() { const { hide, show, visible, animating } = cancelDialog useEffect(() => { if (cancelId) { show() } else { hide() } }, [cancelId, hide, show]) useEffect(() => { if (!visible && !animating) { setCancelId(null) } }, [visible, animating]) } if (transactions.length === 0) return null return (
    {transactions.map(t => (
  • {t.status === 'AWAITING_INPUT' && ( )} {getName(t.action)}
    Started {dateTimeFormatter.format(t.createdAt)}
    { setCancelId(t.id) }} children="Cancel" icon={IconCancel} />
  • ))}
) } export function OrganizationDashboard({ slugPrefix, pageTitle, breadcrumbs, }: { slugPrefix?: string pageTitle?: string breadcrumbs?: ActionGroup[] }) { const { organization, organizationEnvironment } = useDashboard() const result = trpc.useQuery([ 'dashboard.home.index', { slugPrefix, }, ]) { const { remove, refetch } = result useEffect(() => { remove() refetch() }, [organizationEnvironment.id, remove, refetch]) } const queryClient = useQueryClient() const canRunActions = useHasPermission('RUN_PROD_ACTIONS') const canConfigureActions = useHasPermission('WRITE_PROD_ACTIONS') const canDequeue = useHasPermission('DEQUEUE_PROD_ACTIONS') const hasAnyActions = result.data?.actions.length || result.data?.groups.length if (result.isLoading) { return } if (result.isLoading || !result.data) { return } const fallback = (
{result.data && (
{ queryClient.setQueryData( ['dashboard.home.index', { slugPrefix }], { ...result.data, transactions: result.data.transactions.filter( t => t.id !== transaction.id ), } ) }} /> { queryClient.setQueryData( ['dashboard.home.index', { slugPrefix }], { ...result.data, queuedActions: result.data.queuedActions.filter( q => q.id !== queuedAction.id ), } ) }} /> {!hasAnyActions && (result.data?.currentPage ? ( ) : ( ))}
)}
) if (result.data.currentPage?.hasHandler && result.data.currentPage?.canRun) { return ( ) } return fallback } function CancelTransactionForm({ transactionId, onSubmit, onClose, }: { transactionId: string | null onSubmit: (transaction: Transaction) => void onClose: () => void }) { const cancel = trpc.useMutation(['transaction.cancel']) return (

Are you sure you want to cancel this transaction?

This cannot be undone.

{ if (!transactionId) return cancel.mutate( { transactionId, }, { onSuccess(transaction) { onSubmit(transaction) onClose() }, } ) }} />
) } export default function OrganizationDashboardPage() { const { orgEnvSlug } = useOrgParams() return }